<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, reactive } from 'vue'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js'
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js'

const containerRef = ref(null)
let scene, camera, renderer, controls, composer
let animationFrameId
let tree,
  textMesh,
  fireflies = []
let leaves = []
let fallingLeaves = []
let messages = []
let hoverObject = null
let stars, ground, groundDecorations
const leafColors = [0x76c043, 0x8fce00, 0x4caf50, 0x81c784, 0xa5d6a7]

// 场景设置
const sceneSettings = reactive({
  isNightMode: true,
  dayBackground: new THREE.Color(0x87ceeb), // 天蓝色
  nightBackground: new THREE.Color(0x001122), // 深蓝色
  dayFog: new THREE.FogExp2(0x87ceeb, 0.01),
  nightFog: new THREE.FogExp2(0x001122, 0.02),
  dayGroundColor: 0x4caf50, // 绿色
  nightGroundColor: 0x113322, // 深绿色
})

// 树洞消息
const treeMessages = [
  '今天考试考砸了，好难过...',
  '暗恋的人今天和我说话了！',
  '室友又熬夜打游戏，我睡不着啊',
  '想家了，但是假期还有一个月',
  '今天在食堂吃到了特别好吃的红烧肉',
  '为什么每次上课都下雨啊',
  '终于把论文写完了，感觉整个人都解脱了',
  '学校的樱花开了，真美',
  '期末季，图书馆都没有座位了',
  '今天在校园里看到一只可爱的小猫',
]

const stats = reactive({
  fps: 0,
  lastFrameTime: 0,
  frameCount: 0,
})

// 切换日夜模式
const toggleDayNight = () => {
  sceneSettings.isNightMode = !sceneSettings.isNightMode

  if (scene) {
    // 更新背景色
    scene.background = sceneSettings.isNightMode
      ? sceneSettings.nightBackground
      : sceneSettings.dayBackground

    // 更新雾效果
    scene.fog = sceneSettings.isNightMode ? sceneSettings.nightFog : sceneSettings.dayFog

    // 更新地面颜色
    if (ground && ground.material) {
      ground.material.color.setHex(
        sceneSettings.isNightMode ? sceneSettings.nightGroundColor : sceneSettings.dayGroundColor,
      )
    }

    // 更新后期处理效果
    if (composer) {
      const bloomPass = composer.passes.find((pass) => pass instanceof UnrealBloomPass)
      if (bloomPass) {
        bloomPass.strength = sceneSettings.isNightMode ? 0.3 : 0.1
      }
    }

    // 显示/隐藏星星
    if (stars) {
      stars.visible = sceneSettings.isNightMode
    }

    // 更新萤火虫可见性
    fireflies.forEach((firefly) => {
      firefly.visible = sceneSettings.isNightMode
    })

    // 更新树洞光源
    if (tree) {
      const holeLight = tree.children.find((child) => child instanceof THREE.PointLight)
      if (holeLight) {
        holeLight.intensity = sceneSettings.isNightMode ? 1 : 0.3
      }
    }
  }
}

// 初始化3D场景
const init3DScene = () => {
  if (!containerRef.value) return

  // 创建场景
  scene = new THREE.Scene()
  scene.background = sceneSettings.isNightMode
    ? sceneSettings.nightBackground
    : sceneSettings.dayBackground
  scene.fog = sceneSettings.isNightMode ? sceneSettings.nightFog : sceneSettings.dayFog

  // 创建相机
  camera = new THREE.PerspectiveCamera(
    75,
    containerRef.value.clientWidth / containerRef.value.clientHeight,
    0.1,
    1000,
  )
  camera.position.z = 10
  camera.position.y = 2

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({
    antialias: true,
    powerPreference: 'high-performance',
  })
  renderer.setSize(containerRef.value.clientWidth, containerRef.value.clientHeight)
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
  renderer.shadowMap.enabled = true
  renderer.shadowMap.type = THREE.PCFSoftShadowMap
  renderer.outputColorSpace = THREE.SRGBColorSpace
  renderer.toneMapping = THREE.ACESFilmicToneMapping
  renderer.toneMappingExposure = 1.2

  // 确保DOM元素存在再进行appendChild操作
  if (containerRef.value) {
    containerRef.value.appendChild(renderer.domElement)
  } else {
    console.error('containerRef DOM元素不存在')
    return // 如果DOM不存在则退出初始化
  }

  // 设置后期处理
  setupPostprocessing()

  // 添加轨道控制
  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true
  controls.dampingFactor = 0.05
  controls.maxDistance = 20
  controls.minDistance = 5
  controls.maxPolarAngle = Math.PI / 2 - 0.1
  controls.target.set(0, 2, 0)

  // 添加灯光
  setupLights()

  // 添加星空背景
  createStarfield()

  // 添加地面
  createGround()

  // 创建树
  createTree()

  // 创建萤火虫
  createFireflies()

  // 创建3D文字
  createText()

  // 添加树洞消息
  createTreeMessages()

  // 添加事件监听器
  renderer.domElement.addEventListener('click', onSceneClick)
  renderer.domElement.addEventListener('mousemove', onMouseMove)
  window.addEventListener('resize', onResize)

  // 开始动画循环
  animate()
}

// 设置后期处理
const setupPostprocessing = () => {
  composer = new EffectComposer(renderer)

  const renderPass = new RenderPass(scene, camera)
  composer.addPass(renderPass)

  const bloomPass = new UnrealBloomPass(
    new THREE.Vector2(window.innerWidth, window.innerHeight),
    sceneSettings.isNightMode ? 0.3 : 0.1, // 强度
    0.4, // 半径
    0.85, // 阈值
  )
  composer.addPass(bloomPass)
}

// 设置灯光
const setupLights = () => {
  // 环境光
  const ambientLight = new THREE.AmbientLight(
    sceneSettings.isNightMode ? 0x334455 : 0x9dc5bb,
    sceneSettings.isNightMode ? 0.5 : 0.8,
  )
  scene.add(ambientLight)

  // 主光源 (月光/太阳光)
  const mainLight = new THREE.DirectionalLight(
    sceneSettings.isNightMode ? 0x8899bb : 0xffffee,
    sceneSettings.isNightMode ? 0.8 : 1.2,
  )
  mainLight.position.set(5, 10, 5)
  mainLight.castShadow = true
  mainLight.shadow.mapSize.width = 2048
  mainLight.shadow.mapSize.height = 2048
  mainLight.shadow.camera.near = 0.5
  mainLight.shadow.camera.far = 50
  mainLight.shadow.camera.left = -15
  mainLight.shadow.camera.right = 15
  mainLight.shadow.camera.top = 15
  mainLight.shadow.camera.bottom = -15
  mainLight.shadow.bias = -0.0005
  scene.add(mainLight)

  // 树洞内部的神秘光源
  const holeLight = new THREE.PointLight(0x00ffff, sceneSettings.isNightMode ? 1 : 0.3, 5)
  holeLight.position.set(0, 0.8, 0.6)
  tree?.add(holeLight)

  // 地面上的点光源
  const groundLight = new THREE.PointLight(
    sceneSettings.isNightMode ? 0x3388ff : 0x88ccff,
    sceneSettings.isNightMode ? 0.8 : 0.4,
    10,
  )
  groundLight.position.set(0, 0.1, 0)
  groundLight.castShadow = true
  scene.add(groundLight)
}

// 创建星空背景
const createStarfield = () => {
  const starsGeometry = new THREE.BufferGeometry()
  const starsMaterial = new THREE.PointsMaterial({
    color: 0xffffff,
    size: 0.1,
    transparent: true,
    opacity: 0.8,
    sizeAttenuation: true,
  })

  const starsVertices = []
  for (let i = 0; i < 3000; i++) {
    const x = (Math.random() - 0.5) * 200
    const y = (Math.random() - 0.5) * 200
    const z = (Math.random() - 0.5) * 200

    // 确保星星在远处
    if (Math.abs(x) < 30 && Math.abs(y) < 30 && Math.abs(z) < 30) continue

    starsVertices.push(x, y, z)
  }

  starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3))
  stars = new THREE.Points(starsGeometry, starsMaterial)
  stars.visible = sceneSettings.isNightMode
  scene.add(stars)
}

// 创建地面
const createGround = () => {
  // 创建草地纹理
  const groundGeometry = new THREE.CircleGeometry(12, 64)

  // 使用自定义着色器材质创建带有波纹效果的地面
  const groundMaterial = new THREE.MeshStandardMaterial({
    color: sceneSettings.isNightMode
      ? sceneSettings.nightGroundColor
      : sceneSettings.dayGroundColor,
    roughness: 0.8,
    metalness: 0.2,
    wireframe: false,
  })

  ground = new THREE.Mesh(groundGeometry, groundMaterial)
  ground.rotation.x = -Math.PI / 2
  ground.position.y = -1
  ground.receiveShadow = true
  scene.add(ground)

  // 添加一些装饰性的石头和花朵
  groundDecorations = new THREE.Group()
  scene.add(groundDecorations)
  addGroundDecorations()
}

// 添加地面装饰
const addGroundDecorations = () => {
  // 添加石头
  for (let i = 0; i < 15; i++) {
    const rockGeometry = new THREE.DodecahedronGeometry(0.3, 0)
    const rockMaterial = new THREE.MeshStandardMaterial({
      color: 0x555555,
      roughness: 0.9,
      metalness: 0.1,
    })

    const rock = new THREE.Mesh(rockGeometry, rockMaterial)

    // 随机位置
    const angle = Math.random() * Math.PI * 2
    const radius = 3 + Math.random() * 8

    rock.position.set(
      Math.cos(angle) * radius,
      -0.8 + Math.random() * 0.3,
      Math.sin(angle) * radius,
    )
    rock.rotation.set(Math.random() * Math.PI, Math.random() * Math.PI, Math.random() * Math.PI)
    rock.scale.set(0.2 + Math.random() * 0.4, 0.2 + Math.random() * 0.4, 0.2 + Math.random() * 0.4)
    rock.castShadow = true
    rock.receiveShadow = true

    groundDecorations.add(rock)
  }

  // 添加花朵
  for (let i = 0; i < 20; i++) {
    const flowerGroup = new THREE.Group()

    // 花茎
    const stemGeometry = new THREE.CylinderGeometry(0.02, 0.02, 0.6, 8)
    const stemMaterial = new THREE.MeshStandardMaterial({
      color: 0x33aa33,
      roughness: 0.8,
    })
    const stem = new THREE.Mesh(stemGeometry, stemMaterial)
    stem.position.y = 0.2
    flowerGroup.add(stem)

    // 花瓣
    const petalGeometry = new THREE.SphereGeometry(0.1, 8, 8, 0, Math.PI * 2, 0, Math.PI / 2)
    const petalMaterial = new THREE.MeshStandardMaterial({
      color: new THREE.Color().setHSL(Math.random(), 0.8, 0.6),
      roughness: 0.5,
      metalness: 0.1,
      emissive: 0x111111,
    })

    for (let j = 0; j < 5; j++) {
      const petal = new THREE.Mesh(petalGeometry, petalMaterial)
      const angle = (j / 5) * Math.PI * 2
      petal.position.set(Math.cos(angle) * 0.1, 0.5, Math.sin(angle) * 0.1)
      petal.scale.set(0.8, 0.8, 0.8)
      flowerGroup.add(petal)
    }

    // 花蕊
    const centerGeometry = new THREE.SphereGeometry(0.05, 8, 8)
    const centerMaterial = new THREE.MeshStandardMaterial({
      color: 0xffff00,
      roughness: 0.3,
      metalness: 0.3,
      emissive: 0x333300,
    })
    const center = new THREE.Mesh(centerGeometry, centerMaterial)
    center.position.y = 0.5
    flowerGroup.add(center)

    // 随机位置
    const angle = Math.random() * Math.PI * 2
    const radius = 4 + Math.random() * 6
    flowerGroup.position.set(Math.cos(angle) * radius, -0.5, Math.sin(angle) * radius)
    flowerGroup.rotation.y = Math.random() * Math.PI * 2

    groundDecorations.add(flowerGroup)
  }
}

// 创建树
const createTree = () => {
  tree = new THREE.Group()

  // 树干
  const trunkGeometry = new THREE.CylinderGeometry(0.5, 0.7, 3, 12)
  const trunkMaterial = new THREE.MeshStandardMaterial({
    color: 0x8b4513,
    roughness: 0.9,
    metalness: 0.1,
    flatShading: true,
  })
  const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial)
  trunk.position.y = 0.5
  trunk.castShadow = true
  trunk.receiveShadow = true
  trunk.userData.isTreePart = true
  tree.add(trunk)

  // 树洞
  const holeGeometry = new THREE.SphereGeometry(0.4, 32, 16, 0, Math.PI * 2, 0, Math.PI / 2)
  const holeMaterial = new THREE.MeshStandardMaterial({
    color: 0x3e2723,
    roughness: 1,
    metalness: 0,
    side: THREE.DoubleSide,
    emissive: 0x001122,
    emissiveIntensity: 0.2,
  })
  const hole = new THREE.Mesh(holeGeometry, holeMaterial)
  hole.position.set(0, 0.8, 0.5)
  hole.rotation.x = Math.PI / 2
  hole.scale.set(1, 0.7, 1)
  hole.userData.isTreePart = true
  tree.add(hole)

  // 树根
  createTreeRoots()

  // 树冠（多个球体组成）
  createTreeCrown()

  scene.add(tree)
}

// 创建树根
const createTreeRoots = () => {
  const rootMaterial = new THREE.MeshStandardMaterial({
    color: 0x5d4037,
    roughness: 0.9,
    metalness: 0.1,
  })

  const rootDetailMaterial = new THREE.MeshStandardMaterial({
    color: 0x6d4c41,
    roughness: 0.9,
    metalness: 0.1,
  })

  // 添加几个主要的树根
  for (let i = 0; i < 5; i++) {
    const angle = (i / 5) * Math.PI * 2
    const mainRootGeometry = new THREE.CylinderGeometry(0.2, 0.1, 1.2, 8)
    const mainRoot = new THREE.Mesh(mainRootGeometry, rootMaterial)
    mainRoot.position.set(Math.cos(angle) * 0.5, -0.6, Math.sin(angle) * 0.5)

    // 旋转根部使其向外延伸
    mainRoot.rotation.x = Math.PI / 2.5
    mainRoot.rotation.z = -angle

    tree.add(mainRoot)

    // 为每个主根添加一些小根
    for (let j = 0; j < 3; j++) {
      const subRootGeometry = new THREE.CylinderGeometry(0.05, 0.02, 0.5, 6)
      const subRoot = new THREE.Mesh(subRootGeometry, rootDetailMaterial)

      // 小根的位置
      const subAngle = angle + (Math.random() - 0.5) * 0.5
      const distance = 0.8 + Math.random() * 0.3

      subRoot.position.set(
        Math.cos(subAngle) * distance,
        -0.9 - Math.random() * 0.2,
        Math.sin(subAngle) * distance,
      )

      // 随机旋转
      subRoot.rotation.x = Math.PI / 2 + (Math.random() - 0.5) * 0.5
      subRoot.rotation.z = -subAngle + (Math.random() - 0.5) * 0.5

      tree.add(subRoot)
    }
  }
}

// 创建树冠
const createTreeCrown = () => {
  // 树冠位置
  const crownPositions = [
    { x: 0, y: 3, z: 0, radius: 2 },
    { x: 1.5, y: 2.5, z: 0, radius: 1.5 },
    { x: -1.5, y: 2.5, z: 0, radius: 1.5 },
    { x: 0, y: 2.5, z: 1.5, radius: 1.5 },
    { x: 0, y: 2.5, z: -1.5, radius: 1.5 },
    { x: 1, y: 4, z: 0, radius: 1.2 },
    { x: -1, y: 4, z: 0, radius: 1.2 },
    { x: 0, y: 4, z: 1, radius: 1.2 },
    { x: 0, y: 4, z: -1, radius: 1.2 },
    { x: 0, y: 5, z: 0, radius: 1.3 },
  ]

  // 为每个位置创建一个球体
  crownPositions.forEach((pos) => {
    const crownGeometry = new THREE.SphereGeometry(pos.radius, 16, 16)

    // 添加一些随机噪声使树冠不那么完美
    const noise = {
      x: (Math.random() - 0.5) * 0.3,
      y: (Math.random() - 0.5) * 0.3,
      z: (Math.random() - 0.5) * 0.3,
    }

    const crownMaterial = new THREE.MeshStandardMaterial({
      color: 0x2e7d32,
      roughness: 0.8,
      metalness: 0.2,
      flatShading: false,
    })

    const crown = new THREE.Mesh(crownGeometry, crownMaterial)
    crown.position.set(pos.x + noise.x, pos.y + noise.y, pos.z + noise.z)
    crown.castShadow = true
    crown.receiveShadow = true
    tree.add(crown)

    // 为每个树冠球体添加一些叶子
    createLeaves(crown, 30)
  })
}

// 创建叶子
const createLeaves = (crown, count) => {
  const crownPosition = new THREE.Vector3()
  crown.getWorldPosition(crownPosition)

  for (let i = 0; i < count; i++) {
    // 使用更自然的叶子形状 - 扁平的四面体
    const leafGeometry = new THREE.TetrahedronGeometry(0.2, 0)

    // 压扁叶子
    const positionAttribute = leafGeometry.getAttribute('position')
    const vertex = new THREE.Vector3()

    for (let j = 0; j < positionAttribute.count; j++) {
      vertex.fromBufferAttribute(positionAttribute, j)
      vertex.y *= 0.3 // 压扁Y轴
      positionAttribute.setXYZ(j, vertex.x, vertex.y, vertex.z)
    }

    leafGeometry.computeVertexNormals()

    // 随机选择叶子颜色，增加变化
    const colorIndex = Math.floor(Math.random() * leafColors.length)
    const leafMaterial = new THREE.MeshStandardMaterial({
      color: leafColors[colorIndex],
      roughness: 0.7,
      metalness: 0.1,
      side: THREE.DoubleSide,
    })

    const leaf = new THREE.Mesh(leafGeometry, leafMaterial)

    // 随机位置（在球体表面附近）
    const phi = Math.random() * Math.PI * 2
    const theta = Math.random() * Math.PI
    const radius = crown.geometry.parameters.radius * 0.95

    const x = crownPosition.x + radius * Math.sin(theta) * Math.cos(phi)
    const y = crownPosition.y + radius * Math.sin(theta) * Math.sin(phi)
    const z = crownPosition.z + radius * Math.cos(theta)

    leaf.position.set(x, y, z)

    // 随机旋转，但保持叶子朝外
    leaf.lookAt(
      leaf.position
        .clone()
        .add(
          new THREE.Vector3(
            (Math.random() - 0.5) * 0.5,
            (Math.random() - 0.5) * 0.5,
            (Math.random() - 0.5) * 0.5,
          ),
        ),
    )

    leaf.castShadow = true
    leaf.userData = {
      originalPosition: new THREE.Vector3(x, y, z),
      crownCenter: crownPosition.clone(),
      isLeaf: true,
    }

    scene.add(leaf)
    leaves.push(leaf)
  }
}

// 创建萤火虫
const createFireflies = () => {
  const fireflyMaterial = new THREE.PointsMaterial({
    size: 0.15,
    map: createFireflyTexture(),
    transparent: true,
    opacity: 0.8,
    blending: THREE.AdditiveBlending,
    depthWrite: false,
  })

  for (let i = 0; i < 50; i++) {
    const fireflyGeometry = new THREE.BufferGeometry()
    const position = new Float32Array(3)

    // 随机位置，主要在树周围
    const angle = Math.random() * Math.PI * 2
    const radius = 2 + Math.random() * 6
    const height = Math.random() * 6

    position[0] = Math.cos(angle) * radius
    position[1] = height
    position[2] = Math.sin(angle) * radius

    fireflyGeometry.setAttribute('position', new THREE.BufferAttribute(position, 3))

    const firefly = new THREE.Points(fireflyGeometry, fireflyMaterial.clone())
    firefly.material.color.setHSL(
      Math.random() * 0.2 + 0.5, // 黄绿到青色
      0.8,
      0.6,
    )

    // 添加动画数据
    firefly.userData = {
      originalPosition: new THREE.Vector3(position[0], position[1], position[2]),
      speed: Math.random() * 0.01 + 0.005,
      amplitude: Math.random() * 2 + 1,
      phase: Math.random() * Math.PI * 2,
      blinkSpeed: Math.random() * 0.05 + 0.02,
    }

    firefly.visible = sceneSettings.isNightMode
    scene.add(firefly)
    fireflies.push(firefly)
  }
}

// 创建萤火虫纹理
const createFireflyTexture = () => {
  const canvas = document.createElement('canvas')
  canvas.width = 32
  canvas.height = 32

  const context = canvas.getContext('2d')
  const gradient = context.createRadialGradient(16, 16, 0, 16, 16, 16)
  gradient.addColorStop(0, 'rgba(255, 255, 255, 1)')
  gradient.addColorStop(0.2, 'rgba(255, 255, 200, 1)')
  gradient.addColorStop(0.4, 'rgba(200, 255, 150, 0.8)')
  gradient.addColorStop(0.8, 'rgba(150, 255, 100, 0.2)')
  gradient.addColorStop(1, 'rgba(100, 255, 50, 0)')

  context.fillStyle = gradient
  context.fillRect(0, 0, 32, 32)

  const texture = new THREE.CanvasTexture(canvas)
  return texture
}

// 创建3D文字
const createText = () => {
  const loader = new FontLoader()

  loader.load('/fonts/helvetiker_regular.typeface.json', (font) => {
    const textGeometry = new TextGeometry('西科树洞', {
      font: font,
      size: 0.5,
      height: 0.1,
      curveSegments: 12,
      bevelEnabled: true,
      bevelThickness: 0.03,
      bevelSize: 0.02,
      bevelOffset: 0,
      bevelSegments: 5,
    })

    // 居中文字
    textGeometry.computeBoundingBox()
    const centerOffset = -0.5 * (textGeometry.boundingBox.max.x - textGeometry.boundingBox.min.x)

    const textMaterial = new THREE.MeshStandardMaterial({
      color: 0x66ccff,
      metalness: 0.5,
      roughness: 0.2,
      emissive: 0x003366,
      emissiveIntensity: 0.5,
    })

    textMesh = new THREE.Mesh(textGeometry, textMaterial)
    textMesh.castShadow = true
    textMesh.position.x = centerOffset
    textMesh.position.y = -0.8
    textMesh.position.z = 0

    scene.add(textMesh)
  })
}

// 创建树洞消息
const createTreeMessages = () => {
  const messageGroup = new THREE.Group()

  treeMessages.forEach((message, index) => {
    // 创建消息气泡
    const bubbleGeometry = new THREE.SphereGeometry(0.3, 16, 16, 0, Math.PI * 2, 0, Math.PI / 2)
    const bubbleMaterial = new THREE.MeshStandardMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 0.7,
      side: THREE.DoubleSide,
      emissive: 0x6699cc,
      emissiveIntensity: 0.2,
    })

    const bubble = new THREE.Mesh(bubbleGeometry, bubbleMaterial)

    // 随机位置，围绕树洞
    const angle = (index / treeMessages.length) * Math.PI * 2
    const distance = 0.8 + Math.random() * 0.3

    bubble.position.set(
      Math.cos(angle) * distance,
      0.8 + Math.random() * 0.5,
      Math.sin(angle) * distance,
    )

    bubble.rotation.x = Math.PI / 2
    bubble.scale.set(1, 0.6, 1)
    bubble.visible = false // 初始隐藏

    // 添加消息文本
    const canvas = document.createElement('canvas')
    canvas.width = 256
    canvas.height = 128

    const context = canvas.getContext('2d')
    context.fillStyle = 'rgba(0, 0, 0, 0.7)'
    context.fillRect(0, 0, canvas.width, canvas.height)
    context.fillStyle = 'white'
    context.font = '14px Arial'

    // 文本换行处理
    const maxWidth = 240
    const lineHeight = 18
    let y = 30

    for (let i = 0; i < message.length; i += 12) {
      const textChunk = message.substr(i, 12)
      context.fillText(textChunk, 10, y)
      y += lineHeight

      if (y > 110) break // 防止文本溢出
    }

    const texture = new THREE.CanvasTexture(canvas)
    const textMaterial = new THREE.MeshBasicMaterial({
      map: texture,
      transparent: true,
      opacity: 0.9,
      side: THREE.DoubleSide,
    })

    const textGeometry = new THREE.PlaneGeometry(0.8, 0.4)
    const textMesh = new THREE.Mesh(textGeometry, textMaterial)
    textMesh.position.set(bubble.position.x, bubble.position.y + 0.3, bubble.position.z)
    textMesh.lookAt(camera.position)
    textMesh.visible = false // 初始隐藏

    // 存储消息对象
    const messageObj = {
      bubble,
      text: textMesh,
      angle,
      distance,
      visible: false,
    }

    scene.add(bubble)
    scene.add(textMesh)
    messages.push(messageObj)
  })
}

// 显示/隐藏消息
const toggleMessages = () => {
  const anyVisible = messages.some((msg) => msg.visible)

  if (anyVisible) {
    // 隐藏所有消息
    messages.forEach((msg) => {
      msg.bubble.visible = false
      msg.text.visible = false
      msg.visible = false
    })
  } else {
    // 显示所有消息
    messages.forEach((msg) => {
      msg.bubble.visible = true
      msg.text.visible = true
      msg.visible = true
    })
  }
}

// 高亮显示特定消息
const highlightMessage = (index) => {
  const msg = messages[index]

  // 放大该消息
  msg.bubble.scale.set(1.2, 0.7, 1.2)
  msg.text.scale.set(1.2, 1.2, 1.2)

  // 恢复其他消息大小
  messages.forEach((m, i) => {
    if (i !== index && m.visible) {
      m.bubble.scale.set(1, 0.6, 1)
      m.text.scale.set(1, 1, 1)
    }
  })
}

// 场景点击事件
const onSceneClick = (event) => {
  event.preventDefault()

  // 计算鼠标位置
  const mouse = new THREE.Vector2()
  mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1
  mouse.y = -(event.clientY / renderer.domElement.clientHeight) * 2 + 1

  // 射线检测
  const raycaster = new THREE.Raycaster()
  raycaster.setFromCamera(mouse, camera)

  // 检测树干和树洞
  const intersects = raycaster.intersectObjects(scene.children, true)

  if (intersects.length > 0) {
    const object = intersects[0].object

    // 点击树干或树洞
    if (object.userData.isTreePart) {
      // 显示/隐藏消息
      toggleMessages()
      return
    }

    // 点击叶子
    if (object.userData.isLeaf) {
      // 让叶子掉落
      makeLeavesFall(10 + Math.floor(Math.random() * 10))
      return
    }

    // 点击消息气泡
    const messageIndex = messages.findIndex((msg) => msg.bubble === object || msg.text === object)
    if (messageIndex >= 0) {
      // 放大显示该消息
      highlightMessage(messageIndex)
      return
    }
  }

  // 点击空白处，让一些叶子掉落
  makeLeavesFall(5)
}

// 鼠标移动事件
const onMouseMove = (event) => {
  event.preventDefault()

  // 计算鼠标位置
  const mouse = new THREE.Vector2()
  mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1
  mouse.y = -(event.clientY / renderer.domElement.clientHeight) * 2 + 1

  // 射线检测
  const raycaster = new THREE.Raycaster()
  raycaster.setFromCamera(mouse, camera)

  // 检测物体
  const intersects = raycaster.intersectObjects(scene.children, true)

  // 重置之前的悬停对象
  if (hoverObject) {
    if (hoverObject.userData.isLeaf) {
      hoverObject.material.emissive.setHex(0x000000)
    }
    hoverObject = null
    document.body.style.cursor = 'default'
  }

  if (intersects.length > 0) {
    const object = intersects[0].object

    // 悬停在树干、树洞或叶子上
    if (object.userData.isTreePart || object.userData.isLeaf) {
      hoverObject = object
      document.body.style.cursor = 'pointer'

      if (object.userData.isLeaf) {
        // 高亮叶子
        object.material.emissive.setHex(0x333333)
      }
    }

    // 悬停在消息上
    const messageIndex = messages.findIndex((msg) => msg.bubble === object || msg.text === object)
    if (messageIndex >= 0) {
      document.body.style.cursor = 'pointer'
    }
  }
}

// 让叶子掉落
const makeLeavesFall = (count) => {
  // 随机选择一些叶子
  const availableLeaves = leaves.filter((leaf) => !fallingLeaves.includes(leaf))
  if (availableLeaves.length === 0) return

  const leavesToFall = []
  for (let i = 0; i < Math.min(count, availableLeaves.length); i++) {
    const randomIndex = Math.floor(Math.random() * availableLeaves.length)
    leavesToFall.push(availableLeaves.splice(randomIndex, 1)[0])
  }

  // 让选中的叶子开始掉落
  leavesToFall.forEach((leaf) => {
    // 保存原始位置
    if (!leaf.userData.originalPosition) {
      leaf.userData.originalPosition = leaf.position.clone()
    }

    // 添加随机速度
    leaf.userData.velocity = new THREE.Vector3(
      (Math.random() - 0.5) * 0.05,
      -0.02 - Math.random() * 0.03,
      (Math.random() - 0.5) * 0.05,
    )

    // 添加随机旋转速度
    leaf.userData.rotationSpeed = {
      x: (Math.random() - 0.5) * 0.05,
      y: (Math.random() - 0.5) * 0.05,
      z: (Math.random() - 0.5) * 0.05,
    }

    // 添加到掉落列表
    fallingLeaves.push(leaf)
  })
}

// 更新掉落的叶子
const updateFallingLeaves = () => {
  for (let i = fallingLeaves.length - 1; i >= 0; i--) {
    const leaf = fallingLeaves[i]

    // 更新位置
    leaf.position.add(leaf.userData.velocity)

    // 添加一些摇摆效果
    leaf.userData.velocity.x += (Math.random() - 0.5) * 0.002
    leaf.userData.velocity.z += (Math.random() - 0.5) * 0.002

    // 更新旋转
    leaf.rotation.x += leaf.userData.rotationSpeed.x
    leaf.rotation.y += leaf.userData.rotationSpeed.y
    leaf.rotation.z += leaf.userData.rotationSpeed.z

    // 如果叶子落到地面
    if (leaf.position.y < -0.8) {
      // 移除掉落状态
      fallingLeaves.splice(i, 1)

      // 渐渐消失
      setTimeout(
        () => {
          // 将叶子移回原位
          leaf.position.copy(leaf.userData.originalPosition)
        },
        5000 + Math.random() * 2000,
      )
    }
  }
}

// 更新萤火虫
const updateFireflies = () => {
  const time = Date.now() * 0.001

  fireflies.forEach((firefly) => {
    const data = firefly.userData
    const newPosition = data.originalPosition.clone()

    // 添加随机运动
    newPosition.x += Math.sin(time * data.speed + data.phase) * data.amplitude * 0.3
    newPosition.y += Math.cos(time * data.speed * 0.7 + data.phase) * data.amplitude * 0.2
    newPosition.z += Math.sin(time * data.speed * 0.5 + data.phase) * data.amplitude * 0.3

    // 更新位置
    firefly.geometry.attributes.position.array[0] = newPosition.x
    firefly.geometry.attributes.position.array[1] = newPosition.y
    firefly.geometry.attributes.position.array[2] = newPosition.z
    firefly.geometry.attributes.position.needsUpdate = true

    // 闪烁效果
    const blinkFactor = 0.7 + 0.3 * Math.sin(time * data.blinkSpeed * 5)
    firefly.material.opacity = blinkFactor
  })
}

// 更新消息
const updateMessages = () => {
  const time = Date.now() * 0.001

  messages.forEach((msg, index) => {
    if (msg.visible) {
      // 轻微浮动效果
      const floatY = Math.sin(time * 0.5 + index * 0.2) * 0.03
      msg.bubble.position.y =
        msg.bubble.position.y * 0.95 + (0.8 + floatY + Math.random() * 0.5) * 0.05
      msg.text.position.y = msg.bubble.position.y + 0.3

      // 始终面向相机
      msg.text.lookAt(camera.position)
    }
  })
}

// 窗口大小变化处理
const onResize = () => {
  if (!containerRef.value) return

  camera.aspect = containerRef.value.clientWidth / containerRef.value.clientHeight
  camera.updateProjectionMatrix()

  renderer.setSize(containerRef.value.clientWidth, containerRef.value.clientHeight)
  composer.setSize(containerRef.value.clientWidth, containerRef.value.clientHeight)
}

// 动画循环
const animate = () => {
  animationFrameId = requestAnimationFrame(animate)

  // 计算FPS
  const now = performance.now()
  stats.frameCount++

  if (now >= stats.lastFrameTime + 1000) {
    stats.fps = Math.round((stats.frameCount * 1000) / (now - stats.lastFrameTime))
    stats.lastFrameTime = now
    stats.frameCount = 0
  }

  // 轻微摇动树
  if (tree) {
    tree.rotation.y = Math.sin(Date.now() * 0.0005) * 0.05
  }

  // 更新掉落的叶子
  updateFallingLeaves()

  // 更新萤火虫
  updateFireflies()

  // 更新消息
  updateMessages()

  // 更新控制器
  if (controls) controls.update()

  // 使用后期处理渲染场景
  composer.render()
}

// 组件挂载时初始化场景
onMounted(() => {
  // 延迟初始化Three.js，确保DOM已经完全渲染
  setTimeout(() => {
    try {
      init3DScene()
    } catch (error) {
      console.error('初始化3D场景失败:', error)
    }
  }, 200)
})

// 组件卸载前清理资源
onBeforeUnmount(() => {
  // 移除事件监听器
  renderer?.domElement.removeEventListener('click', onSceneClick)
  renderer?.domElement.removeEventListener('mousemove', onMouseMove)
  window.removeEventListener('resize', onResize)

  // 停止动画
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId)
  }

  // 释放THREE.js资源
  if (renderer) {
    renderer.dispose()
  }

  // 释放几何体和材质
  if (scene) {
    scene.traverse((object) => {
      if (object.geometry) {
        object.geometry.dispose()
      }

      if (object.material) {
        if (Array.isArray(object.material)) {
          object.material.forEach((material) => material.dispose())
        } else {
          object.material.dispose()
        }
      }
    })
  }

  // 清除引用
  scene = null
  camera = null
  renderer = null
  controls = null
  composer = null
})
</script>

<template>
  <div class="three-d-logo-container">
    <div ref="containerRef" class="canvas-container"></div>

    <!-- 日夜切换按钮 -->
    <button class="toggle-mode-btn" @click="toggleDayNight">
      <span v-if="sceneSettings.isNightMode">☀️ 切换到白天模式</span>
      <span v-else>🌙 切换到夜晚模式</span>
    </button>

    <div class="interaction-hint">
      <p>点击树木查看树洞消息 | 点击叶子让它们飘落 | 拖动旋转 | 滚轮缩放</p>
    </div>
    <div class="fps-counter" v-if="stats.fps > 0">FPS: {{ stats.fps }}</div>
  </div>
</template>

<style scoped>
.three-d-logo-container {
  position: relative;
  width: 100%;
  height: 400px;
  margin-bottom: 24px;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.canvas-container {
  width: 100%;
  height: 100%;
}

.toggle-mode-btn {
  position: absolute;
  top: 10px;
  left: 10px;
  background-color: rgba(190, 241, 173, 0.878);
  color: white;
  border: none;
  border-radius: 20px;
  padding: 8px 16px;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.3s ease;
  backdrop-filter: blur(4px);
  z-index: 10;
}

.toggle-mode-btn:hover {
  background-color: rgba(190, 241, 173, 0.878);
  transform: translateY(-2px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.interaction-hint {
  position: absolute;
  bottom: 10px;
  left: 0;
  right: 0;
  text-align: center;
  color: #fff;
  font-size: 14px;
  background-color: rgba(0, 0, 0, 0.5);
  padding: 8px;
  border-radius: 4px;
  margin: 0 auto;
  width: fit-content;
  backdrop-filter: blur(4px);
}

.fps-counter {
  position: absolute;
  top: 10px;
  right: 10px;
  background-color: rgba(0, 0, 0, 0.5);
  color: #fff;
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-family: monospace;
  backdrop-filter: blur(4px);
}
</style>
